package com.ch.websocketdemo.socket;

import com.ch.websocketdemo.socket.decode.ServerEncoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 94366
 */
@Slf4j
@ServerEndpoint(value = "/ws/{token}", encoders = {ServerEncoder.class})
@Component
public class WebSocketServer {
    /**
     * 当前在线连接数
     */
    private static final AtomicInteger ONLINE_NUM = new AtomicInteger();

    /**
     * 在线用户session
     * <p>key - token</p>
     * <p>value - session</p>
     */
    private static final ConcurrentHashMap<String, Session> SESSION_POOL = new ConcurrentHashMap<>();
    /**
     * 建立连接成功调用
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "token") String token){
        log.info("新管理员尝试进行WebSocket连接...");
        // todo 校验token

        // 将成功的token session存储起来
        SESSION_POOL.put(token, session);
        addOnlineCount();
        log.info("管理员上线成功,当前在线数量:【{}】", ONLINE_NUM);

        WebSocketUtil.sendMessage(session, "欢迎你的到来！");
    }

    /**
     * 关闭连接时调用
     */
    @OnClose
    public void onClose(@PathParam(value = "token") String token) {
        // 移除存储的session
        if (SESSION_POOL.containsKey(token)) {
            SESSION_POOL.remove(token);
            subOnlineCount();
        }
        log.info("断开webSocket连接,当前在线人数：【{}】", ONLINE_NUM);
    }

    /**
     * 收到客户端信息
     */
    @OnMessage
    public void onMessage(String message) throws IOException {
        log.info("收到客户端消息");
    }

    /**
     * 错误时调用
     */
    @OnError
    public void onError(Session session, Throwable throwable) {
        throwable.printStackTrace();
    }

    public static void addOnlineCount() {
        ONLINE_NUM.incrementAndGet();
    }

    public static void subOnlineCount() {
        ONLINE_NUM.decrementAndGet();
    }

    /**
     * 查看当前在线会话中是否包含该token
     *
     * @param token String
     * @return boolean
     */
    public static boolean checkToken(String token) {
        return SESSION_POOL.containsKey(token);
    }

    public static ConcurrentMap<String, Session> getSessionPool() {
        return SESSION_POOL;
    }
}
